package com.cjm.one.goods.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cjm.one.common.exception.GlobalException;
import com.cjm.one.common.exception.OptimisticLockException;
import com.cjm.one.common.result.ResultCodeEnum;
import com.cjm.one.goods.mapper.GoodsSkuMapper;
import com.cjm.one.goods.service.GoodsSkuService;
import com.cjm.one.model.goods.dto.StockDeductionDTO;
import com.cjm.one.model.goods.dto.StockRevertDTO;
import com.cjm.one.model.goods.entity.GoodsBrowseHistory;
import com.cjm.one.model.goods.entity.GoodsInfo;
import com.cjm.one.model.goods.entity.GoodsSku;
import com.cjm.one.model.goods.enums.SortStrategyEnum;
import com.cjm.one.model.goods.vo.GoodsSkuVo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author 29289
* @description 针对表【goods_sku】的数据库操作Service实现
* @createDate 2024-09-05 16:07:00
*/
@Service
@Slf4j
public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku>
    implements GoodsSkuService {
    @Resource
    private GoodsSkuMapper baseMapper;
    @Override
    public Page<GoodsSku> pageList(Long current, Long size, Long categoryId, String name, SortStrategyEnum strategyEnum) {
        if (current == null || current < 1) current = 1L;
        if (size == null || size < 1) size = 10L;
        // 创建分页对象
        Page<GoodsSku> page = new Page<>(current, size);

        // 构建查询条件
        LambdaQueryWrapper<GoodsSku> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(GoodsSku::getStatus, 1);           // 只显示已上架商品
         // 未删除商品

        // 一级分类过滤
        if (categoryId != null) {
            wrapper.eq(GoodsSku::getCategory1Id, categoryId);
        }

        // SKU名称模糊查询
        if (StringUtils.hasText(name)) {
            wrapper.like(GoodsSku::getSkuName, name);
        }

        // 处理排序策略（默认随机）
        SortStrategyEnum strategy = strategyEnum != null ? strategyEnum : SortStrategyEnum.RANDOM;
        switch (strategy) {
            case RANDOM:
                wrapper.last("ORDER BY RAND()");  // MySQL随机排序
                break;
            case PRICE_ASC:
                wrapper.orderByAsc(GoodsSku::getSalePrice);
                break;
            case PRICE_DESC:
                wrapper.orderByDesc(GoodsSku::getSalePrice);
                break;
            case SALES_DESC: // 销量降序（保持兼容）
                wrapper.orderByDesc(GoodsSku::getSaleNum);
                break;
            default:
                wrapper.last("ORDER BY RAND()");
        }

        return baseMapper.selectPage(page, wrapper);
    }
    @Cacheable(
            value = "goodsSkuPageListByCategoryId",
            key = "#root.methodName + '_' + #categoryId + '_' + #current + '_' + #size"
    )
    @Override
    public Page<GoodsSku> pageListByCategoryId(Long categoryId, Long current, Long size) {
        if (current == null || current < 1) {
            current = 1L;
        }
        if (size == null || size < 1) {
            size = 10L;
        }
        LambdaQueryWrapper<GoodsSku> goodsSkuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        goodsSkuLambdaQueryWrapper.eq(GoodsSku::getCategory2Id, categoryId);
        Page<GoodsSku> page = new Page<>(current, size);
        Page<GoodsSku> goodsSkuPage = baseMapper.selectPage(page, goodsSkuLambdaQueryWrapper);
        return goodsSkuPage;
    }

    @Override
    public Page<GoodsSkuVo> pageListByCollection(Long id, Long current, Long size) {
        //根据用户id查询收藏商品列表
        Page<GoodsSkuVo> page = new Page<>(current, size);
        page.setSize(Math.min(page.getSize(), 100L));
        return baseMapper.selectPageByCollection(page, id);
    }

    @Override
    public Page<GoodsSku> getByUserBrowseHistory(Integer current, Integer size, Long id) {
        size = Math.min(size, 100);
        return baseMapper.selectPageByBrowseHistory(new Page<>(current, size), id);
    }

    @Override
    public Page<GoodsSku> getSkuCouponList(Long[] ids) {
        Page<GoodsSku> goodsSkuPage = new Page<>(1,40);

        LambdaQueryWrapper<GoodsSku> goodsSkuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        goodsSkuLambdaQueryWrapper.in(GoodsSku::getId, ids);
        return baseMapper.selectPage(goodsSkuPage, goodsSkuLambdaQueryWrapper);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deductionStock(List<StockDeductionDTO> deductionList) {
        // 1. 校验库存充足性
        List<Long> skuIds = deductionList.stream()
                .map(StockDeductionDTO::getSkuId)
                .distinct()
                .collect(Collectors.toList());

        Map<Long, GoodsSku> skuMap = baseMapper.selectBatchIds(skuIds)
                .stream()
                .collect(Collectors.toMap(GoodsSku::getId, sku -> sku));

        // 2. 数据预处理
        List<StockDeductionDTO> validSkus = deductionList.stream()
                .map(item -> {
                    GoodsSku sku = skuMap.get(item.getSkuId());
                    if (sku == null) {
                        throw new GlobalException(ResultCodeEnum.GOODS_NOT_FOUND);
                    }
                    if (sku.getStockNum() < item.getSkuNum()) {
                        throw new GlobalException(ResultCodeEnum.STOCK_NOT_ENOUGH);
                    }
                    item.setVersion(sku.getVersion());
                    return item;
                })
                .collect(Collectors.toList());

        // 3. 执行批量更新
        int affectedRows = baseMapper.batchDeductionStock(validSkus);

        // 4. 处理部分更新失败
        if (affectedRows < validSkus.size()) {
            throw new GlobalException(ResultCodeEnum.STOCK_CONCURRENCY_FAILED);
        }

        return true;
    }
    /**
     * @description: 回退库存
     * @author: cjm
     * @date: 2025/3/30 16:23
     * @param: [ids]
     * @return: java.lang.Boolean
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean revertStock(List<StockRevertDTO> stockRevertDTOS) {
        // 1. 校验可回滚库存
        List<Long> skuIds = stockRevertDTOS.stream()
                .map(StockRevertDTO::getSkuId)
                .collect(Collectors.toList());

        Map<Long, GoodsSku> skuMap = baseMapper.selectBatchIds(skuIds)
                .stream()
                .collect(Collectors.toMap(GoodsSku::getId, sku -> sku));

        // 2. 数据预处理
        List<StockRevertDTO> validList = stockRevertDTOS.stream()
                .map(item -> {
                    GoodsSku sku = skuMap.get(item.getSkuId());
                    if (sku == null) {
                        throw new GlobalException(ResultCodeEnum.GOODS_NOT_FOUND);
                    }
                    if (sku.getPreStock() < item.getQuantity()) {
                        throw new GlobalException(ResultCodeEnum.STOCK_NOT_ENOUGH);
                    }
                    item.setVersion(sku.getVersion());
                    return item;
                })
                .collect(Collectors.toList());

        // 3. 执行回滚
        int affectedRows = baseMapper.batchRevertStock(validList);
        log.info("回滚库存影响的行数: {}", affectedRows);
        // 4. 结果处理
        if (affectedRows != validList.size()) {
            throw new OptimisticLockException("库存回滚版本冲突");
        }

        return true;
    }

}




